package vip.xiaonuo.modular.attendancerecord.service;

import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.facedoor.modular.memberuser.entity.MemberUser;
import vip.xiaonuo.modular.attendancedayset.entity.AttendanceDaySet;
import vip.xiaonuo.modular.attendancedayset.param.AttendanceDaySetParam;
import vip.xiaonuo.modular.attendancegroup.entity.AttendanceGroup;
import vip.xiaonuo.modular.attendancerecord.entity.AttendanceRecord;
import vip.xiaonuo.modular.attendanceshift.entity.AttendanceShift;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Service
public class AttendancePlanService extends AttendancePlanBaseService{

    public void createPlan(AttendanceGroup group)  {
        this.check(group);

        // 获取人员
        List<MemberUser> users = this.getMemberUsers(group.getOrgIds());
        if(users == null || users.size() == 0){
            throw new ServiceException(500,"用户组下没有用户！");
        }
        // 获取班次
        List<AttendanceShift> shifts = this.getAttendanceShifts(group.getAttendanceShiftIds());
        if(shifts == null || shifts.size() == 0){
            throw new ServiceException(500,"未定义班次！");
        }
        // 获取考勤日期
        List<Date> dates = this.getAttendanceDays(group);
        if(dates == null || dates.size() == 0){
            throw new ServiceException(500,"未定义日期！");
        }
        // 循环生成考勤计划
        List<AttendanceRecord> toSave = new ArrayList<>();
        for(Date date : dates){
            this.doCreatePlan(toSave,date,group,users,shifts);
        }
        if( toSave.size() == 0){
            throw new ServiceException(500,"未保存任何数据！");
        }
        recordService.saveBatch(toSave);
    }


    /**
     * 获取考勤日期，下个月
     * @param group
     * @return
     */
    private List<Date> getAttendanceDays(@NotNull AttendanceGroup group) {
        int daySource = group.getWorkDaysSource();
        Calendar cal = Calendar.getInstance();

        if(daySource == 0 ){ // 法定(需要外网接口，暂不处理)
            return getDatesLegal(cal);
        }else if(daySource == 1){ // 排除节假日
            return getDatesExcludeHoliday(cal);
        }else if(daySource == 2){ // 仅自定义工作日
            return getDatesIncludeWorkDay(cal);
        }else if(daySource == 3){ // 自定义排班
            return null;
        }else if(daySource == 4){ // 弹性工作制
            return getFullMonth(cal);
        }
        return null;
    }

    private List<Date> getFullMonth(Calendar cal) {
        cal.add(Calendar.MONTH,1);
        List<Date> dates = new ArrayList<>();
        for(int i = 1 ; i < cal.getActualMaximum(Calendar.DATE) ; i++){
            cal.set(Calendar.DATE,i);
            dates.add(cal.getTime());
        }
        return dates;
    }

    /**
     * 排除节假日
     * @return
     */
    private List<Date> getDatesExcludeHoliday(@NotNull Calendar cal){
        cal.add(Calendar.MONTH,1);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");

        AttendanceDaySetParam param = new AttendanceDaySetParam();
        param.setWorkdayOrHoliday(1);
        param.setMonth(sdf.format(cal.getTime()));
        List<AttendanceDaySet> daySets = daySetMapper.listMonth(param);

        List<Date> dates = new ArrayList<>();
        for(int i = 1 ; i < cal.getActualMaximum(Calendar.DATE) ; i++){
            cal.set(Calendar.DATE,i);
            Date day = cal.getTime();
            if(!isBetween(day,daySets)){
                dates.add(day);
            }
        }
        return dates;
    }

    /**
     * 仅工作日
     * @return
     */
    private List<Date> getDatesIncludeWorkDay(Calendar cal){
        cal.add(Calendar.MONTH,1);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");

        AttendanceDaySetParam param = new AttendanceDaySetParam();
        param.setWorkdayOrHoliday(2);
        param.setMonth(sdf.format(cal.getTime()));
        List<AttendanceDaySet> daySets = daySetMapper.listMonth(param);
        long oneDay = 24 * 60 * 60 * 1000;
        List<Date> dates = new ArrayList<>();
        for(AttendanceDaySet daySet : daySets){
            Date startDate = daySet.getStartDate();
            Date endDate = daySet.getEndDate();

            while(startDate.getTime()<=endDate.getTime()){
                dates.add(new Date(startDate.getTime()));
                startDate.setTime(startDate.getTime() + oneDay);
            }
        }
        return dates;
    }

    private List<Date> getDatesLegal(@NotNull Calendar cal){
        cal.add(Calendar.MONTH,1);
        List<Date> dates = new ArrayList<>();
        for(int i = 1 ; i < cal.getActualMaximum(Calendar.DATE) ; i++){
            cal.set(Calendar.DATE,i);
            Date day = cal.getTime();
            if(!nextDayIsWorkDay(day)){
                dates.add(day);
            }
        }
        return dates;
    }



}
